package com.lyy.lottery.dao.handler;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.lyy.lottery.dao.dataobject.Encrypt;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//处理 Java类型 Encrypt和数据库类型 VARCHAR 之间的映射
@MappedTypes(Encrypt.class)//该处理器处理的java类型
@MappedJdbcTypes(JdbcType.VARCHAR)//处理器处理的Jdbc类型
public class EncryptTypeHandler extends BaseTypeHandler<Encrypt> {

    private final byte[] KEYS="1234567890abcdef".getBytes(StandardCharsets.UTF_8);//密钥的特定长度：16字节（128位）、24字节（192位）或32字节（256位）

    //将 Java类型的 Encrypt对象转换为数据库中的 VARCHAR类型，并设置到 PreparedStatement中
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Encrypt param, JdbcType jdbcType) throws SQLException {
        if (param==null || param.getValue()==null){
            ps.setString(i,null);
            return;
        }
        AES aes= SecureUtil.aes(KEYS);
        String encrypt=aes.encryptHex(param.getValue());
        //使用 AES加密算法对 Encrypt对象中的值进行加密，并将加密后的字符串设置到 SQL参数中
        ps.setString(i,encrypt);
    }

    //将数据库中的加密字符串解密为 Encrypt对象
    public Encrypt decrypt(String value){
        if (null==value)
            return null;
        AES aes= SecureUtil.aes(KEYS);
        return new Encrypt(aes.decryptStr(value));
    }

    //根据结果集中指定列名获取值，并将其解密为 Encrypt对象
    @Override
    public Encrypt getNullableResult(ResultSet rs, String columName) throws SQLException {
        return decrypt(rs.getString(columName));
    }

    //根据结果集中指定列索引获取值，并将其解密为 Encrypt对象
    @Override
    public Encrypt getNullableResult(ResultSet rs, int columIndex) throws SQLException {
        return decrypt(rs.getString(columIndex));
    }

    //根据 CallableStatement中指定列索引获取值，并将其解密为 Encrypt对象
    @Override
    public Encrypt getNullableResult(CallableStatement cs, int columIndex) throws SQLException {
        return decrypt(cs.getString(columIndex));
    }
}
